﻿#region Disclaimer/Info
///////////////////////////////////////////////////////////////////////////////////////////////////
// MetaCollection
// 
// MetaCollection is a system to provide a standard structure, permissions and metadata service
// for content organization.
//
// This project is hosted at Google Code at http://code.google.com/p/metacollection/
//
// This project is licensed under the BSD license.  See the License.txt file for more information.
///////////////////////////////////////////////////////////////////////////////////////////////////
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Community.CsharpSqlite.SQLiteClient;
using MetaCollection.Framework.Model;

namespace MetaCollection.SqliteRepository
{
	public class AuditRepository : MetaCollection.Framework.Repository.IAuditRepository
	{
		private string m_ConnectionString;
		private bool m_Initialized;

		/// <summary>
		/// Ensures the repository has been initialized.
		/// </summary>
		/// <exception cref="InvalidOperationException">Thrown if <see cref="AdoNetItem.Initialize"/> has not been called.</exception>
		private void EnsureInitialized()
		{
			if (!m_Initialized)
				throw new InvalidOperationException("Resource Provider must be initialized prior to use.");
		}

		#region IRepository Members

		/// <summary>
		/// Initializes a new instance of the IItemRepository
		/// </summary>
		/// <param name="configData"></param>
		public void Initialize(string configData)
		{
			m_ConnectionString = configData;
			m_Initialized = true;
		}

		#endregion

		#region IAuditRepository Members

		/// <summary>
		/// Gets the audited events for the given item (using the Item's ID)
		/// </summary>
		/// <param name="item">item to pull the Id off of</param>
		/// <returns>A listing of all of the audited events for an item.</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities", Justification = "SQL comes from a resource file and is parameterized.")]
		public IEnumerable<Framework.Model.IItemAudit> GetItemEvents(Framework.Model.IItemInstance item)
		{
			EnsureInitialized();

			if (item == null)
				throw new ArgumentNullException("item", "Item cannot be null.");

			using (SqliteConnection sqlConn = new SqliteConnection(m_ConnectionString))
			{
				sqlConn.Open();
				using (var command = new SqliteCommand(Resources.EventSelectSql, sqlConn))
				{
					command.Parameters.Add("@id", item.Id.ToString().ToUpperInvariant());
					var reader = command.ExecuteReader();
					while (reader.Read())
					{
						var evt = new SqliteItemAudit();
						evt.Id = new Guid(reader.GetString(reader.GetOrdinal("Id")));
						evt.ItemId = new Guid(reader.GetString(reader.GetOrdinal("ItemId")));
						evt.ItemVersion = reader.GetInt32(reader.GetOrdinal("Version"));
						evt.EventDate = reader.GetDateTime(reader.GetOrdinal("EventDate"));
						evt.EventType = reader.GetString(reader.GetOrdinal("EventType"));
						evt.Message = reader.GetString(reader.GetOrdinal("Message"));
						yield return (IItemAudit)evt;
					}
				}
			}
		}

		/// <summary>
		/// Logs an Audit Event into the database for the given item.
		/// </summary>
		/// <param name="item">Item to log the event on</param>
		/// <param name="eventType">Type of Audit Event</param>
		/// <param name="message">Message associated with the event.</param>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities", Justification = "SQL comes from a resource file and is parameterized.")]
		public void SaveItemEvent(Framework.Model.IItemInstance item, string eventType, string message)
		{
			EnsureInitialized();

			if (item == null)
				throw new ArgumentNullException("item", "Item cannot be null.");

			if (string.IsNullOrEmpty(eventType))
				throw new ArgumentNullException("eventType", "Event Type is required.");

			using (SqliteConnection sqlConn = new SqliteConnection(m_ConnectionString))
			{
				sqlConn.Open();
				using (var writeData = new SqliteCommand(Resources.EventInsertSql, sqlConn))
				{
					writeData.Parameters.Add("@id", Guid.NewGuid().ToString().ToUpperInvariant());
					writeData.Parameters.Add("@itemId", item.Id.ToString().ToUpperInvariant());
					writeData.Parameters.Add("@version", item.Version);
					writeData.Parameters.Add("@eventDate", DateTime.Now);
					writeData.Parameters.Add("@eventType", eventType);
					writeData.Parameters.Add("@message", message);
					writeData.ExecuteNonQuery();
				}
			}
		}

		#endregion
	}
}
